export default {

    genMapper(ast){
        let method = ast.call;
        let importPack = [];
        let fullName = ast.parameters.find(i=>i.name=='type').value;
        importPack.push(fullName);
        let fetch = ast.parameters.find(i=>i.name=='fetch');
        let type = fetch?fetch.value:'obj';
        let {packageName,cName} = this.getClass(fullName);
        var returnType;
        if(type=='list'){
            returnType = `List<${cName}>`
            importPack.push('java.util.List')
        }else{
            returnType = cName
        }
        return {
             type:returnType,
             method,
             import:importPack,
             packageName: packageName
        }
    },
    genSql(ast){

        let cols = [];

        let rootMap = this.getDupMap(ast);

        function walkTree(tree,res){
          tree.properties.forEach(i=>{
            if(i.calls){
              let sres = [];
              walkTree(i.properties,sres)
              res.push(...sres)
            }else{
              res.push(`${i.alias}.${i.name} ${i.jname?i.jname:''}`)
            }
          })
        }

        ast.properties.forEach(i=>{
          if(i.calls){
            let res = [];
            walkTree(i.properties,res)
            cols.push(...res)
          }else{
            let name = `${i.alias}.${i.name} ${i.jname?i.jname:''}`
            cols.push(name);
          }

        })

//        cols = cols.map(i=>{
//           if(rootMap[i]){
//               //与其他字段重复
//               return `${i} as ${rootMap[i]}`
//           }
//           return i;
//       })

        return {
          method: ast.call,
          sql:`select ${cols.join(',')} from ${ast.querybody}`
        };
    	},
    	getDupMap(ast){
    	    let colNameMap = {};
    	    let cols = [];
    	    let dupMap = {};
    	    function genAlias(ali,name){
    	        return ali+name+'_1'
    	    }

    	    function walkTree(tree,res){
              tree.properties.forEach(i=>{
                if(i.calls){
                  let sres = [];
                  walkTree(i.properties,sres)
                  res.push(...sres)
                }else{
                   if(colNameMap[i.name]){
                    //重复
                    dupMap[`${i.alias}.${i.name}`] = genAlias(i.alias,i.name)
                   }else{
                    colNameMap[i.name]=true
                   }
                  res.push(`${i.alias}.${i.name}`)
                }
              })
            }

            ast.properties.forEach(i=>{
              if(i.calls){
                let res = [];
                walkTree(i.properties,res)
                cols.push(...res)
              }else{
                let name = `${i.alias}.${i.name}`
                if(colNameMap[i.name]){
                    //重复字段
                    //添加 as 别名
                    dupMap[`${i.alias}.${i.name}`] = genAlias(i.alias,i.name)
                }else{
                    colNameMap[i.name]=true
                }

                cols.push(name);
              }
            })
            console.log(dupMap)
            return dupMap;
    	},
    genResultMapper(ast){
        let rows = [];

        let rootMap = this.getDupMap(ast);
        ast.properties.forEach(prop=>{
           let colName = prop.name;
           if(rootMap[`${prop.alias}.${prop.name}`]){
               //与其他字段重复
               colName = rootMap[prop.name]
           }
          if(prop.calls){
            this.genSubMapperRow(prop,rootMap,rows);
          }else{
            rows.push(this.genRow(prop));
          }
        })
        return {
            method:ast.call,
            bean:ast.parameters.find(i=>i.name=='type').value,
            fields:rows
          }
      },
      genInnerMapperRow(props,rootMap){
        return props.map(prop=>{
          if(prop.calls){
              let srows=[];
              this.genSubMapperRow(prop,rootMap,srows);
              return "\t"+srows.join("\n");
          }
          let colName = prop.name;
          let key = `${prop.alias}.${prop.name}`;
          if(rootMap[key]){
              //与其他字段重复
              colName = rootMap[key]
          }
          return this.genRow(prop);
        });
      },
      genSubMapperRow(prop,rootMap,rows){
          if(prop.calls){
           let srows = [];
           let config = this.toMap(prop.calls.find(i=>i.call=='config').parameters);
           if(config.fetch=='list'){
             srows.push(`<collection property="${prop.name}" ofType="${config.type}">`);
             srows.push(...this.genInnerMapperRow(prop.properties.properties,rootMap));
             srows.push(`</collection>`);
           }else{
             srows.push(`<association property="${prop.name}" javaType="${config.type}">`);
             srows.push(...this.genInnerMapperRow(prop.properties.properties,rootMap));
             srows.push(`</association>`)
           }
           rows.push(...srows);
         }else{
           rows.push(this.genRow(prop));
         }
      },
    genRow(prop){
            let jname = prop.jname?this.toHump(prop.jname):this.toHump(prop.name);
            if(prop.alias&&prop.name=='*'){
                jname=prop.alias;
            }
            let cname = prop.name;
            if(prop.jname){
                cname=prop.jname;
            }
            return `<result property="${jname}" column="${cname}"></result>`;
    },
  genMapperRow(props,rootMap){
      //TODO 是否能够嵌套？
      return props.map(prop=>{
        if(prop.calls){

        }
        let colName = prop.name;
        let key = `${prop.alias}.${prop.name}`;
//        if(rootMap[key]){
            //与其他字段重复
//            colName = rootMap[key]
//        }
        console.log(prop)
        let jname = prop.jname?this.toHump(prop.jname):this.toHump(prop.name)
        if(colName=='*'){
            return `<result alias="${prop.alias}" property="${jname}" column="${colName}"></result>`;
        }
        return `<result property="${jname}" column="${colName}"></result>`;
      });
    },
  genRootBean(ast){
    let fields = this.genProp(ast.properties)
    let rootFName = ast.parameters.find(i=>i.name=='type').value;
    let classInfo = this.getClass(rootFName)
    let rootBean = {...classInfo,fields}
    //生成rootbean
    return rootBean;
  },
  genBean(rootBean,res){

      let importPack = []
      let cName = rootBean.cName;
      let fields = []
      for(var bean of rootBean.fields){
        if(bean.fields){
          //生成关联类
          if(bean.isList){
            importPack.push('java.util.List');
          }
          importPack.push(`${bean.packageName}.${bean.cName}`);
          this.genBean(bean,res)
        }
        fields.push({
            name:bean.name,
            type:bean.type,
            colName: bean.colName,
            tname: bean.tname,
            alias: bean.alias
        })
      }

      res.push({
          import:importPack,
          className:cName,
          packageName:rootBean.packageName,
          fields:fields
        })
    },
    genProp(props){
        return props.map(p=>{
          if(p.calls){
            return this.genSub(p);
          }
          return {
            name: p.jname?this.toHump(p.jname):this.toHump(p.name),
            colName: p.jname?p.jname:p.name,
            tname: p.name,
            type: p.type,
            alias: p.alias
          }
        });
      },
    genSub(subBean){
        //只支持嵌套一层
        let rootFName = subBean.calls[0].parameters.find(i=>i.name=='type').value;
        let config = subBean.calls[0].parameters.reduce((t,c)=>{
          t[c.name]=c.value
          return t;
        },{});

        let fetchType = config.fetch;
        let beanName = config.type;
        let {packageName,cName} = this.getClass(beanName)
        let humpName = this.toHump(cName)
        return {
          name: subBean.name,
          beanName,
          packageName:packageName,
          cName,
          fields:this.genProp(subBean.properties.properties),
          type: fetchType=='list'?`List<${cName}>`:cName,
          isList: fetchType=='list'?true:false
        }
  },

toMap(parameters){
    return parameters.reduce((t,c)=>{
      t[c.name]=c.value
      return t;
    },{});
  },

  toHump(name) {
      return name.replace(/\_(\w)/g, function(all, letter){
          return letter.toUpperCase();
      });
  },
  // 驼峰转换下划线
  toLine(name) {
    return name.replace(/([A-Z])/g,"_$1").toLowerCase();
  },

  toHumpUpper(name) {
    return upper(toHump(name));
  },

  upper(str){
   var strTemp = ""; //新字符串
   for(var i=0;i<str.length;i++){
    if(i == 0){
     strTemp += str[i].toUpperCase(); //第一个
     continue;
    }
    if(str[i] == " " && i< str.length-1){ //空格后
     strTemp += " ";
     strTemp += str[i+1].toUpperCase();
     i++;
     continue;
    }
    strTemp += str[i];
   }
    return strTemp;
   },

    getClass(fname){
        return {
          packageName:fname.substring(0,fname.lastIndexOf('.')),
          cName:fname.substring(fname.lastIndexOf('.')+1)
        }
     }

}